/**
 * 
 */
package edu.pku.sei.modeler.editparts;

import java.beans.PropertyChangeEvent;
import java.util.List;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.editpolicies.DirectEditPolicy;
import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.requests.ReconnectRequest;

import edu.pku.sei.modeler.editpolicies.NestedNodeLayoutEditPolicy;
import edu.pku.sei.modeler.editpolicies.UMLDiagramGraphicalNodeEditPolicy;
import edu.pku.sei.modeler.figures.StructuredClassFigure;
import edu.pku.sei.modeler.model.core.MetaElement;
import edu.pku.sei.modeler.model.structure.MetaLink;
import edu.pku.sei.modeler.model.structure.MetaNode;
import edu.pku.sei.modeler.model.structure.MetaShapeElement;
import edu.pku.sei.modeler.model.structure.StructurePackage;
import edu.pku.sei.modeler.model.uml.Dependencies.Dependency;
import edu.pku.sei.modeler.model.uml.Dependencies.Usage;
import edu.pku.sei.modeler.model.uml.Ports.Port;
import edu.pku.sei.modeler.model.uml.StructuredClasses.StructuredClass;
import edu.pku.sei.modeler.uml.commands.ChangeNameCommand;
import edu.pku.sei.modeler.uml.commands.UMLConnectionCreateCommand;
import edu.pku.sei.modeler.uml.commands.compositestructure.CompositeStructureDiagramConnectionCreateFactory;

/**
 * @author YanYan
 *
 */
public class StructuredClassEditpart extends AbstractUMLNodeEditPart{

	public StructuredClassEditpart(MetaShapeElement model) {
		super(model);
	}
	@Override
	protected DirectEditPolicy createDirectEditPolicy() {
		return new DirectEditPolicy() {
			protected Command getDirectEditCommand(DirectEditRequest request) {
				return new ChangeNameCommand(getModelElement(),
						(String) request.getCellEditor().getValue());
			}

			protected void showCurrentEditValue(DirectEditRequest request) {
				IFigure fig = getDirectEditFigure();
				if (fig instanceof Label) {
					((Label) fig).setText(getModelElement().getName());
					fig.getUpdateManager().performUpdate();
				}
			}
		};
	}

	protected StructuredClass getModelElement() {
		return (StructuredClass) ((MetaNode) this.getModel()).getModelElement();
	}

	@Override
	protected IFigure getDirectEditFigure() {
		return ((StructuredClassFigure) this.getFigure()).getNameLabel();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure() {
		StructuredClassFigure structuredClassFigure = new StructuredClassFigure(new Label());

		return structuredClassFigure;
	}

	@Override
	protected void createEditPolicies() {
		super.createEditPolicies();
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new NestedNodeLayoutEditPolicy(((MetaNode)this.getModel()).getDiagram().getType()){
			protected Command getCreateCommand(CreateRequest request) {
				MetaNode node = (MetaNode) request.getNewObject();
				MetaNode hostNode = (MetaNode) this.getHost().getModel();
				if (node.getModelElement() instanceof Port)
					return this.createFactory.createCommand(node,
									hostNode, new Rectangle(request
											.getLocation().getCopy(),
											new Dimension(0,0)));
				return this.createFactory.createCommand(node, hostNode,
						(Rectangle) getConstraintFor(request));
			}
		}); 

		installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE,
				new UMLDiagramGraphicalNodeEditPolicy(((MetaNode)this.getModel()).getDiagram().getType()));
	}

	protected void handlePropertyChanged(PropertyChangeEvent event) {
		String propertyName = event.getPropertyName();
		if (propertyName.equals(StructurePackage.NODE_HEIGHT)) {
			refreshVisuals();
			noticeUseInterface();
		} else if (propertyName.equals(StructurePackage.NODE_WIDTH)) {
			refreshVisuals();
			noticeUseInterface();
		} else if (propertyName.equals(StructurePackage.NODE_LOCATIONX)) {
			refreshVisuals();
			noticeUseInterface();
		} else if (propertyName.equals(StructurePackage.NODE_LOCATIONY)) {
			refreshVisuals();
			noticeUseInterface();
		}
		refreshVisuals();
		super.handlePropertyChanged(event);
	}

	protected void refreshVisuals() {
		StructuredClass model = this.getModelElement();
		StructuredClassFigure figure = (StructuredClassFigure) this.getFigure();

		figure.getNameLabel().setText(model.getName());

		super.refreshVisuals();
		MetaNode node = (MetaNode) getModel();
	}

	private void noticeUseInterface() {
		MetaNode node = (MetaNode) getModel();
		for (int i = 0; i < node.getOutgoings().size(); i++) {
			MetaLink link = (MetaLink) node.getOutgoings().get(i);
			if (link.getModelElement() instanceof Usage) {
				// change property value of UseInterface, in order to force
				// UseInterface
				// refresh visual
				link.getTarget().setWidth(link.getTarget().getWidth() + 3);
			}
		}
	}

	@Override
	public IFigure getContentPane() {
		if (getFigure() instanceof StructuredClassFigure) {
			return ((StructuredClassFigure) getFigure()).getBody();
		}

		return super.getFigure();
	}
}
